/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#pragma once

#ifdef _WIN32
#define ExportSymbol  __declspec(dllexport)
#else
#define ExportSymbol
#endif

#include <string>
#include <list>
#include <map>

namespace NahidaProject {
	class ExportSymbol JSON {
	public:
		enum ExportSymbol Type { jsonNull = 0, jsonBool, jsonInt, jsonDouble, jsonString, jsonArray, jsonObject };

		JSON();
		JSON(Type type);
		JSON(bool value);
		JSON(int value);
		JSON(double value);
		JSON(const char* value);
		JSON(const std::string& value);
		JSON(const JSON& other);
		~JSON();

		Type type() const;

		bool IsNull() const;
		bool IsBool() const;
		bool IsInt() const;
		bool IsDouble() const;
		bool IsString() const;
		bool IsArray() const;
		bool IsObject() const;

		bool AsBool() const;
		int AsInt() const;
		double AsDouble() const;
		std::string AsString() const;

		// number of values in array or object
		int Size() const;

		// return true if empty array, empty object, or null, otherwise, false.
		bool Empty() const;

		void Clear();

		bool Has(int index);
		bool Has(const char* key);
		bool Has(const std::string& key);

		void Remove(int index);
		void Remove(const char* key);
		void Remove(const std::string& key);

		// append value to array at the end.
		void Append(const JSON& value);

		JSON& operator = (const JSON& other);
		bool operator == (const JSON& other);
		bool operator != (const JSON& other);

		JSON& operator [] (int index);
		JSON& operator [] (const char* key);
		JSON& operator [] (const std::string& key);

		operator bool();
		operator int();
		operator double();
		operator std::string();

		void Parse(const std::string& str);
		std::string ToString() const;

		typedef std::list<JSON>::iterator iterator;
		iterator begin()
		{
			return (this->valueType.arrayType)->begin();
		}
		iterator end()
		{
			return (this->valueType.arrayType)->end();
		}

	private:
		void Copy(const JSON& other);

	private:
		union ExportSymbol Value {
			bool booleanType;
			int integerType;
			double doubleType;
			std::string* stringType;
			std::list<JSON>* arrayType;
			std::map<std::string, JSON>* objectType;
		};

		Type typeType;
		Value valueType;
	};
}
